package com.tensquare.notice.netty;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.tensquare.entity.Result;
import com.tensquare.entity.StatusCode;
import com.tensquare.notice.config.ApplicationContextProvider;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;

import java.util.HashMap;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: xxx
 * @Date: 2022/11/13 21:35
 * @Description: websocket处理器
 */
public class MyWebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    
    
    //存放WebSocket连接Map，根据用户Id存放
    public static ConcurrentHashMap<String, Channel> userChannelMap=new ConcurrentHashMap<>();
    
    //json解析工具
    private static ObjectMapper mapper = new ObjectMapper();
    
    //从Spring容器中获取RabbitTemplate
    RabbitTemplate rabbitTemplate= ApplicationContextProvider.getApplicationContext().getBean(RabbitTemplate.class);

    //从Spring容器中获取消息监听器，处理订阅消息
    SimpleMessageListenerContainer sysNoticeContainer= (SimpleMessageListenerContainer) ApplicationContextProvider.getApplicationContext().getBean("sysNoticeContainer");
   
    //从Spring容器中获取消息监听器,处理点赞消息userNotice
    SimpleMessageListenerContainer userNoticeContainer= (SimpleMessageListenerContainer) ApplicationContextProvider.getApplicationContext().getBean("userNoticeContainer");
    
    
    //用户请求WebSocket服务端，执行的方法
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        //约定用户第一次请求携带的数据：{"userId":"1"}
        //获取用户请求数据并解析
        String json = msg.text();
        //解析json数据,获取用户Id
        String userId = mapper.readTree(json).get("userId").asText();
         
        //第一次请求的时候，需要建立WebSocket连接
        Channel channel = userChannelMap.get("userId");
        if (channel==null){
            //获取WebSocket连接
            channel = ctx.channel();
            //把连接放到容器中
            userChannelMap.put(userId, channel);
        }

        //只用完成新消息的提醒即可，只需要获取消息的数量
        //获取RabbitMQ的消息内容，并发送给用户
        RabbitAdmin rabbitAdmin=new RabbitAdmin(rabbitTemplate);

        //-------------------------------------------------------------------------------------------------//
        
        //拼接获取队列名称
        String queueName="article_subscribe_"+userId;
        //获取rabbitMq的队列
        Properties queueProperties = rabbitAdmin.getQueueProperties(queueName);

        int noticeCount=0;
        //判断rabbitmq中有没有队列
        if (queueProperties!=null){
             //获取消息数量
             noticeCount = (int) queueProperties.get("QUEUE_MESSAGE_COUNT");
        }
        
        //--------------上面是获取订阅类消息，下面是获取点赞类消息---------------------------------------------//

        //拼接获取队列名称
        String userQueueName="article_thumbup_" + userId;
        //获取rabbitMq的队列
        Properties userQueueProperties = rabbitAdmin.getQueueProperties(userQueueName);

        int userNoticeCount=0;
        //判断rabbitmq中有没有队列
        if (userQueueProperties!=null){
            //获取消息数量
            userNoticeCount = (int) userQueueProperties.get("QUEUE_MESSAGE_COUNT");
        }

        //-------------------------------------------------------------------------------------------------//
        
        
  
        //封装返回的数据
        HashMap countMap = new HashMap<>();
        //订阅类消息数量
        countMap.put("sysNoticeCount", noticeCount);
        //点赞类消息数量
        countMap.put("userNoticeCount", userNoticeCount);
        Result result=new Result(true, StatusCode.OK,"查询成功",countMap);
        
        //把数据发送给用户
        channel.writeAndFlush(new TextWebSocketFrame(mapper.writeValueAsString(result)));
        
        //把消息从队列中清空，否则MQ消息监听器会再次消费
        if (noticeCount>0){
            rabbitAdmin.purgeQueue(queueName,true);
        }

        if (userNoticeCount>0){
            rabbitAdmin.purgeQueue(userQueueName,true);
        }
        
        //为用户的消息通知队列注册监听器,便于用户在线的时候，
        //一旦有消息，可以主动推送给用户提示有消息，不需要用户再次请求服务器获取数据
        sysNoticeContainer.addQueueNames(queueName);

        userNoticeContainer.addQueueNames(userQueueName);
    }
}
